package com.sunyard.manage.log;

import cn.hutool.json.JSONUtil;
import com.sunyard.constant.manage.CommonConst;
import com.sunyard.dal.bo.operator.OperatorLoginBO;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.SysLog;
import com.sunyard.dal.mapper.OperatorMapper;
import com.sunyard.manage.service.OperatorLogService;
import com.sunyard.manage.util.ExtendsSimpleUtil;
import com.sunyard.utils.DateUtil;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.TokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
    @Autowired
    private OperatorLogService operatorLogService;
    @Autowired
    private OperatorMapper operatorMapper;

    /**
     * @Description 定义一个切点
     */
    @Pointcut("execution(com.sunyard.utils.Response.BaseResult com.sunyard.manage.controller..*.*(..))")
    public void pointcut() {
    }

    /**
     * @param pjp
     * @return
     * @throws Throwable
     * @Description 记录日志到数据库
     */
    @Around("pointcut()")
    public BaseResult around(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();

        BaseResult baseResult = (BaseResult) pjp.proceed();
        try {
            HttpServletRequest request =
                    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String action = request.getServletPath();
            action = action.substring(1, action.length());
            action = action.replace("/", "_");
            String cn = OperateCode.map.get(action);
            //如果为空说明该方法不需要记录日志
            if (StringUtils.isBlank(cn)) {
                return baseResult;
            }
            //登出的做特殊处理，在登出代码中记录日志
            String specStr = "2201";
            if (cn.contains(specStr)) {
                return baseResult;
            }
            SysLog sysLog = buildLog(baseResult, cn, pjp);

            if (!"无".equals(sysLog.getOpId())) {
                sysLog.setCreateDatetime(DateUtil.getDateStr(DateUtil.YYYYMMDD_HHMMSS, new Date()));
                operatorLogService.aspectInsert(sysLog);
            }
            long endTime = System.currentTimeMillis();
            logger.debug("后台处理" + action + "请求花费了:" + (endTime - startTime) + "毫秒");
            return baseResult;
        } catch (Throwable t) {
            logger.error("记录日志出错", t);
            return baseResult;
        }
    }

    public SysLog buildLog(BaseResult baseResult, String cn, ProceedingJoinPoint pjp) {
        String opIp;
        String opId;
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //服务器要是部署在代理服务器上可能会出现异常
        try {
            opIp = ExtendsSimpleUtil.getClientIp(request);
        } catch (Exception e) {
            opIp = "127.0.0.1";
        }
        //请求的参数
        Object[] args = pjp.getArgs();
        List<Object> argsList = new ArrayList<>();
        for (int flag = 0; flag < args.length; flag++) {
            // 如果参数类型是请求和响应的http，则不需要拼接【这两个参数，使用JSON.toJSONString()转换会抛异常】
            if (args[flag] instanceof HttpServletRequest || args[flag] instanceof HttpServletResponse) {
                continue;
            }
            argsList.add(args[flag]);
        }
        //将参数所在的数组转换成json
        String params = JSONUtil.toJsonStr(argsList.get(argsList.size() - 1));
        if (cn.contains("2200")) {
            OperatorLoginBO operatorLoginBO = JSONUtil.toBean(params, OperatorLoginBO.class);
            Operator operatorByOpName = operatorMapper.getOperatorByOpName(operatorLoginBO);
            if(null==operatorByOpName){
                logger.error("登录失败，用户名不存在，参数：{}", params);
                opId="";
            }else{
                opId = operatorByOpName.getOpId();
            }
        } else {
            opId = TokenUtil.getOpId(request.getHeader("token"));
        }
        Operator operator = operatorMapper.getOperatorByOpId(opId);
        SysLog sysLog = new SysLog();
        if (operator != null) {
//            operator.setOrgName(organizationMapper.getOrgName(operator.getOrgId()));
            sysLog.setOpId(operator.getOpId());
            sysLog.setOrgId(operator.getOrgId());
            sysLog.setOpName(operator.getOpName());
        } else {
            sysLog.setOpId("无");
            sysLog.setOpName("无");
        }
//        operatorLog.setSerialNumber(PrimaryKeyUtil.getPrimaryKey(KeyConst.OPERATOR_LOG));
        String[] codeAndName = cn.split(",");
        sysLog.setLogName(codeAndName[1]);

        String code = baseResult.getDataCode();
        if (CommonConst.RET_FAIL.equals(code) || CommonConst.RET_ERROR.equals(code)) {
            sysLog.setOperationDesc("用户" + sysLog.getOpName() + "进行" + codeAndName[1]);
            sysLog.setLogStatus(SysLog.STATUS_FAIL);
        } else {
            sysLog.setOperationDesc("用户" + sysLog.getOpName() + "进行" + codeAndName[1]);
            sysLog.setLogStatus(SysLog.STATUS_SUCCESS);
        }
        return sysLog;
    }


}
